#ifndef RANKSELECTION_H_
#define RANKSELECTION_H_

#include "../Selection.h"
#include "../Roulette/RouletteSelection.h"
#include <algorithm>

/** Implementation of a rank style selection.
 * 
 *    Rank selection is a variant of roulette style selection.  Roulette style
 *  selection favors high fitness solutions over low fitness ones, but if a
 *  single solution has a fitness remarkably higher than the rest of the 
 *  population, it may have such a high chance of being selected that our
 *  population immediately converges to that solution.
 *    Rank Selection solves this by ordering N solutions, and assigning them
 *  a 'fake' fitness based on their rank within the ordered set.  The best 
 *  solution is assigned a fitness of N, the second best is assigned a fitness
 *  of N-1, the next N-2, and so on until the worst solution is assigned a fitness
 *  of 1.  Roulette selection is then performed with these 'fake' fitnesses.
 *    
 *    Note that rank selection does *not* modify the fitness stored within the
 *  solution object.  All temporary fitnesses are tracked internally. 
 */
class RankSelection : public RouletteSelection 
{
    public:
        RankSelection() {};
        void select(Solution* &child1, Solution* &child2); /**< Performs a selection                                     */
        void prepare(vector<Solution*> newPool);           /**< Necessary to accurately perform a selection              */
        
        static Selection* getSelection();
};

#endif /*RANKSELECTION_H_*/
